home *** CD-ROM | disk | FTP | other *** search
- /****************************************************************************/
- /* */
- /* Application: IconDimming */
- /* */
- /* Description: In System 7, selected non-open files are shown as */
- /* dimmed icons on the desktop. This snippet shows */
- /* two different ways to achieve the same results in */
- /* an application. */
- /* */
- /* The first method uses a custom color search */
- /* procedure in place of the current device's to */
- /* create the dimming effect. Once the image has */
- /* been copied to the destination, the custom */
- /* search proc is then removed. */
- /* */
- /* In the second method the RGB components of the */
- /* icon's colortable entries are all dimmed before */
- /* the image is copied into the destination. The */
- /* dimming algorithm used in this method simply */
- /* darkens each RGB component in half then takes */
- /* the two smaller components and darkens them */
- /* in half again. In System 7, this is similar */
- /* to what the Finder does. */
- /* */
- /* Files: IconDimming.π */
- /* IconDimming.c */
- /* IconDimming.π.rsrc */
- /* */
- /* Programmer: Edgar Lee */
- /* Organization: Apple Computer, Inc. */
- /* Department: Developer Technical Support, DTS */
- /* Language: C (Think C version 5.0.1) */
- /* Date Created: 2-27-92 */
- /* */
- /****************************************************************************/
-
- /* Constant Declarations */
-
- #define WWIDTH 480
- #define WHEIGHT 180
-
- #define WLEFT (((screenBits.bounds.right - screenBits.bounds.left) - WWIDTH) / 2)
- #define WTOP (((screenBits.bounds.bottom - screenBits.bounds.top) - WHEIGHT) / 2)
-
- typedef struct
- {
- PixMap pixmap; /* Pixmap used to store the icl8 pixel image. */
- BitMap mask; /* Bitmap used to store the 1 bit mask image of the icl8. */
- }
- MyIconType;
-
- /* Global Variable Definitions */
-
- WindowPtr gWindow;
-
- void initMac();
- void createWindow();
- void loadIconResource();
- void doEventLoop();
-
- void drawIconUnchanged();
- void drawIconUsingSearchProc();
- void drawIconUsingCTable();
-
- void DimColor( RGBColor *aColor );
- long CompareComponents( unsigned short component0, unsigned short component1 );
-
- static pascal Boolean SearchProc();
-
- main()
- {
- MyIconType icon;
-
- initMac();
-
- createWindow();
- loadIconResource( &icon );
-
- doEventLoop( &icon );
- }
-
- void initMac()
- {
- MaxApplZone();
-
- InitGraf( &thePort );
- InitFonts();
- InitWindows();
- InitMenus();
- TEInit();
- InitDialogs( nil );
- InitCursor();
- FlushEvents( 0, everyEvent );
- }
-
- void createWindow()
- {
- Rect rect;
-
- SetRect( &rect, WLEFT, WTOP, WLEFT + WWIDTH, WTOP + WHEIGHT );
-
- gWindow = NewCWindow( 0L, &rect, "\pIconDimming", true, noGrowDocProc,
- (WindowPtr)-1L, true, 0L );
- SetPort( gWindow );
-
- TextFont( geneva );
- TextSize( 9 );
- }
-
- void loadIconResource( icon )
- MyIconType *icon;
- {
- Handle icnHandle; /* Handle to the icon bitmap used for the mask. */
- Handle iclHandle; /* Handle to the icl8 resource. */
- char depth; /* Depth of the icl8 image. */
- Rect rect; /* Bounding rect for the image. */
-
- SetRect( &rect, 0, 0, 32, 32 );
- depth = 8;
-
- /* Create the mask. */
-
- icnHandle = GetResource( 'ICN#', 129 );
-
- HLock( icnHandle );
- HNoPurge( icnHandle );
-
- (*icon).mask.baseAddr = *icnHandle + (4 * 32);
- (*icon).mask.rowBytes = 4;
- (*icon).mask.bounds = rect;
-
- /* Create a pixmap for the icl8 pixel image. */
-
- iclHandle = GetResource( 'icl8', 129 );
-
- HLock( iclHandle );
- HNoPurge( iclHandle );
-
- (*icon).pixmap.baseAddr = *iclHandle;
- (*icon).pixmap.rowBytes = ((32 * depth) / 8) | 0x8000;
- (*icon).pixmap.bounds = rect;
- (*icon).pixmap.pmVersion = 0;
- (*icon).pixmap.packType = 0;
- (*icon).pixmap.packSize = 0;
- (*icon).pixmap.hRes = 72;
- (*icon).pixmap.vRes = 72;
- (*icon).pixmap.pixelSize = depth;
- (*icon).pixmap.planeBytes = 0;
- (*icon).pixmap.pmReserved = 0;
- (*icon).pixmap.pixelType = 0;
- (*icon).pixmap.cmpCount = 1;
- (*icon).pixmap.cmpSize = depth;
- (*icon).pixmap.pmTable = GetCTable( depth );
-
- /* Give a unique seed for the pixmap's colortable. Note that this is */
- /* necessary for two reasons. (1) The pixmap's colortable is ignored by */
- /* copybits or copymask if the source ctable's ctseed value matches that */
- /* of the destination's. (2) Matching ctseed values prevent any custom */
- /* searchProcs from being called. */
-
- (**(*icon).pixmap.pmTable).ctSeed = GetCTSeed();
- }
-
- void drawIconUnchanged( icon )
- MyIconType *icon;
- {
- Str255 title = "\pOriginal 'icl8'";
- Rect rect;
-
- /* Draw the original icl8 image unchanged. */
-
- SetRect( &rect, 0, 0, 160, 160 );
- CopyMask( (BitMap *)&(*icon).pixmap, &(*icon).mask, &gWindow->portBits,
- &(*icon).pixmap.bounds, &(*icon).mask.bounds, &rect );
-
- MoveTo( (rect.right - rect.left - StringWidth( title )) / 2 + rect.left,
- rect.bottom + 15 );
- DrawString( title );
- }
-
- void drawIconUsingSearchProc( icon )
- MyIconType *icon;
- {
- Str255 title = "\p'icl8' using SearchProc Dimming";
- Rect rect;
- GWorldPtr gworld; /* Offscreen used for the custom search procedure. */
- CGrafPtr currentPort; /* Saved CGrafPort for later restore. */
- GDHandle currentDevice; /* Saved gdDevice for later restore. */
-
- GetGWorld( ¤tPort, ¤tDevice );
-
- /* Install the custom search proc to an offscreen pixmap instead of the */
- /* screen's in order to be courteous to other apps. */
-
- NewGWorld( &gworld, 8, &(*icon).pixmap.bounds, GetCTable( 8 ), nil, 0 );
- HLock( (*gworld).portPixMap );
-
- SetGWorld( gworld, nil );
- AddSearch( SearchProc );
-
- CopyBits( &(*icon).pixmap, &(*gworld).portPixMap, &(*icon).pixmap.bounds,
- &(**(*gworld).portPixMap).bounds, srcCopy, nil );
-
- DelSearch( SearchProc );
- SetGWorld( currentPort, currentDevice );
-
- /* Now copy the dimmed pixmap image to the window. */
-
- rect.left = (*icon).pixmap.bounds.right * 5;
- rect.top = (*icon).pixmap.bounds.top;
- rect.right = (*icon).pixmap.bounds.right * 5 + rect.left;
- rect.bottom = (*icon).pixmap.bounds.bottom * 5;
-
- CopyMask( &(*gworld).portPixMap, &(*icon).mask, &gWindow->portBits,
- &(**(*gworld).portPixMap).bounds, &(*icon).mask.bounds, &rect );
-
- DisposeGWorld( gworld );
-
- MoveTo( (rect.right - rect.left - StringWidth( title )) / 2 + rect.left,
- rect.bottom + 15 );
- DrawString( title );
- }
-
- static pascal Boolean SearchProc( color, position )
- RGBColor *color;
- long *position;
- {
- /* Darken the RGB components in half. Note that this routine could just */
- /* have easily called DimColor; however, I wanted to show the difference */
- /* between just dimming the components in half to what System 7 does. */
-
- color->red >>= 1;
- color->green >>= 1;
- color->blue >>= 1;
-
- return false;
- }
-
- void drawIconUsingCTable( icon )
- MyIconType *icon;
- {
- Str255 title = "\p'icl8' using Colortable Dimming";
- Rect rect;
- short index; /* Index into the dimmed colortable */
- CTabHandle dimmedClut; /* Holds dimmed version of icon’s colortable */
- CTabHandle savedClut; /* Saves the icon’s original colortable */
-
- /* Save the icon’s color table and make a copy of it */
- dimmedClut = savedClut = (*icon).pixmap.pmTable;
- HandToHand( (CTabHandle *)&dimmedClut );
-
- /* Dim each of the colors in the copy of the color table */
- for (index = 0; index <= (**dimmedClut).ctSize; ++index)
- DimColor( &(**dimmedClut).ctTable[index].rgb );
-
- /* Install the dimmed copy of the color table */
- (*icon).pixmap.pmTable = dimmedClut;
-
- rect.left = (*icon).pixmap.bounds.right * 10;
- rect.top = (*icon).pixmap.bounds.top;
- rect.right = (*icon).pixmap.bounds.right * 5 + rect.left;
- rect.bottom = (*icon).pixmap.bounds.bottom * 5;
-
- /* Now copy the dimmed pixmap image to the window. */
-
- CopyMask( (BitMap *)&(*icon).pixmap, &(*icon).mask, &gWindow->portBits,
- &(*icon).pixmap.bounds, &(*icon).mask.bounds, &rect );
-
- (*icon).pixmap.pmTable = savedClut;
- DisposCTable( dimmedClut );
-
- MoveTo( (rect.right - rect.left - StringWidth( title )) / 2 + rect.left,
- rect.bottom + 15 );
- DrawString( title );
- }
-
- /******************************************************************************\
- * DimColor - Dim one color for selection
- * written by Forrest Tanaka
- * This routine dims the color that’s passed in the aColor parameter so that
- * it’s suitable to use for making an icon look selected. It works by dimming
- * all components by half, and then dimming the smaller two components by half
- * again. By keeping the largest component dimmed by only half, we keep the
- * saturation of the color approximately what it was before it was dimmed.
- \******************************************************************************/
-
- void DimColor(
- RGBColor *aColor)
- {
- unsigned short *biggest; /* Pointer to the biggest component */
-
- /* Dim all components by half */
- aColor->red >>= 1;
- aColor->green >>= 1;
- aColor->blue >>= 1;
-
- /* If aColor isn’t nearly gray, dim smallest 2 components again by half */
- if (CompareComponents( aColor->red, aColor->green ) != 0 ||
- CompareComponents( aColor->red, aColor->blue ) != 0)
- {
- /* Point to the larger of red and green */
- if (CompareComponents( aColor->red, aColor->green ) > 0)
- biggest = &aColor->red;
- else
- biggest = &aColor->green;
-
- /* Point to the larger of previous test and blue */
- if (CompareComponents( aColor->blue, *biggest ) > 0)
- biggest = &aColor->blue;
-
- /* Dim smaller two components by half */
- if (&aColor->red != biggest)
- aColor->red >>= 1;
- if (&aColor->green != biggest)
- aColor->green >>= 1;
- if (&aColor->blue != biggest)
- aColor->blue >>= 1;
- }
- }
-
- /******************************************************************************\
- * CompareComponents - Compare two components for difference and equality
- * written by Forrest Tanaka
- * This routine compares two components of an RGBColor that are passed in the
- * component0 and component1 parameters. If they’re within 512 units of each
- * other, then zero is returned. Otherwise, the positive difference is returned
- * if component0 is greater than component1, or the negative of the difference
- * is returned if component1 is greater than component0.
- \******************************************************************************/
-
- long CompareComponents(
- unsigned short component0, /* First component to check */
- unsigned short component1) /* Second component to check */
- {
- long difference; /* Difference between components */
-
- /* Calculate the difference between the components */
- difference = (unsigned long)component0 - (unsigned long)component1;
-
- /* If the difference is within 512 units, then consider the components the same */
- if ((difference < 512) && (difference > -512))
- return 0;
- else
- return difference;
- }
-
- void doEventLoop( icon )
- MyIconType *icon;
- {
- EventRecord event;
- WindowPtr window;
- short clickArea;
- Rect screenRect;
-
- for (;;)
- {
- if (WaitNextEvent( everyEvent, &event, 0, nil ))
- {
- if (event.what == mouseDown)
- {
- clickArea = FindWindow( event.where, &window );
-
- if (clickArea == inDrag)
- {
- screenRect = (**GetGrayRgn()).rgnBBox;
- DragWindow( window, event.where, &screenRect );
- }
- else if (clickArea == inContent)
- {
- if (window != FrontWindow())
- SelectWindow( window );
- }
- else if (clickArea == inGoAway)
- if (TrackGoAway( window, event.where ))
- return;
- }
- else if (event.what == updateEvt)
- {
- window = (WindowPtr)event.message;
- SetPort( window );
-
- BeginUpdate( window );
-
- drawIconUnchanged( icon );
- drawIconUsingSearchProc( icon );
- drawIconUsingCTable( icon );
-
- EndUpdate( window );
- }
- }
- }
- }